package cn.jhz.learn.blog.service.core.open.article.impl;

import static java.util.stream.Collectors.toList;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.jhz.learn.blog.component.GLOBAL;
import cn.jhz.learn.blog.component.ValidationHolder;
import cn.jhz.learn.blog.dao.article.*;
import cn.jhz.learn.blog.dao.blogger.BlogBloggerMapper;
import cn.jhz.learn.blog.po.article.BlogArticle;
import cn.jhz.learn.blog.po.article.BlogArticleContent;
import cn.jhz.learn.blog.po.article.BlogArticleSubfieldAssociative;
import cn.jhz.learn.blog.po.blogger.BlogBlogger;
import cn.jhz.learn.blog.service.core.open.article.ArticleService;
import cn.jhz.learn.blog.service.core.open.article.ArticleSubfieldService;
import cn.jhz.learn.blog.util.ObjUtil;
import cn.jhz.learn.blog.util.TextUtil;
import cn.jhz.learn.blog.vo.article.query.view.ArticleView;
import cn.jhz.learn.blog.vo.article.query.page.ArticlePageView;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;

import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

@Validated
@Service("articleService")
public class ArticleServiceImpl implements ArticleService {

	private final BlogBloggerMapper bloggerMapper;
	private final BlogArticleMapper articleMapper;
	private final BlogArticleContentMapper contentMapper;
	private final ArticleSubfieldService articleSubfieldService;
	private final BlogArticleSubfieldAssociativeMapper associativeMapper;
	private final BlogArticleAccessMapper articleAccessMapper;
	private final BlogArticleCommentMapper articleCommentMapper;

	@Autowired
	public ArticleServiceImpl(BlogBloggerMapper bloggerMapper, BlogArticleMapper articleMapper, BlogArticleContentMapper contentMapper, ArticleSubfieldService articleSubfieldService, BlogArticleSubfieldAssociativeMapper associativeMapper, BlogArticleAccessMapper articleAccessMapper, BlogArticleCommentMapper articleCommentMapper) {
		super();
		this.bloggerMapper = bloggerMapper;
		this.articleMapper = articleMapper;
		this.contentMapper = contentMapper;
		this.articleSubfieldService = articleSubfieldService;
		this.associativeMapper = associativeMapper;
		this.articleAccessMapper = articleAccessMapper;
		this.articleCommentMapper = articleCommentMapper;
	}

	@Override
	public PageInfo<ArticleView> getPage(@NotNull ArticlePageView pageView) {
		PageHelper.startPage(pageView.getPage_num(), pageView.getPage_size());

		List<BlogArticle> articleList = Lists.newArrayList();
		Integer subfieldId,blogId;
		List<Byte> type, visibility, status;

		if(pageView.getBlog_name().isPresent()){
			blogId = ((BlogBlogger) ValidationHolder.getParam(GLOBAL.VALIDATION_KEY.CLASS_BLOG_BLOGGER.BLOG_NAME + pageView.getBlog_name().get())).getId();
			visibility =
					ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_BLOG.ARTICLES.VISIBILITY + pageView.getBlog_name().get());
			status = ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_BLOG.ARTICLES.STATUS  + pageView.getBlog_name().get());
			subfieldId = null;
		}else{
			subfieldId = pageView.getSubfield_id().get();
			visibility = ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_SUBFIELD.ARTICLES.VISIBILITY + pageView.getSubfield_id().get());
			status = ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_SUBFIELD.ARTICLES.STATUS  + pageView.getSubfield_id().get());
			blogId = null;
		}

		if(pageView.getOriginal().equals(GLOBAL.PARAM.QUERY.IS_ORIGINAL))
			type = Lists.newArrayList(GLOBAL.RESOURCE.TYPE.ORIGINAL);
		else
			type = Lists.newArrayList(GLOBAL.RESOURCE.TYPE.ALL);

		switch (pageView.getSort()){
			case 0:
				articleList.addAll(articleMapper.selectHotByBlogIdOrSubfieldId(
						blogId,
						subfieldId,
						type,
						visibility,
						status));
				break;
			case 1:
				articleList.addAll(articleMapper.selectLatestByBlogIdOrSubfieldId(
						blogId,
						subfieldId,
						type,
						visibility,
						status));
				break;
			case 2:
				articleList.addAll(articleMapper.selectAccessByBlogIdOrSubfieldId(
						blogId,
						subfieldId,
						type,
						visibility,
						status));
				break;
			default:
				throw new RuntimeException("排序参数异常!:" + pageView.getSort());
		}

		return getArticleOverviews(
				PageInfo.of(articleList) ,
				articleList,
				articleList.isEmpty() ? Lists.newArrayList()
						: contentMapper.batchSelectByPrimaryKeys(articleList.stream().map(BlogArticle::getId).collect(Collectors.toList()))
		);
	}

	@Override
	public PageInfo<ArticleView> getPage(Integer uid, @NotNull ArticlePageView pageView) {
		PageHelper.startPage(pageView.getPage_num(), pageView.getPage_size());

		List<BlogArticle> articleList = Lists.newArrayList();
		List<Byte> visibility, type, status;
		Integer subfieldId = null, blogId = null;

		if (pageView.getBlog_name().isPresent()){
			blogId = ((BlogBlogger)ValidationHolder.getParam(GLOBAL.VALIDATION_KEY.CLASS_BLOG_BLOGGER.BLOG_NAME + pageView.getBlog_name().get())).getId();
			visibility = ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_BLOG.ARTICLES.VISIBILITY + pageView.getBlog_name().get());
			status = ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_BLOG.ARTICLES.STATUS + pageView.getBlog_name().get());
		}else{
			subfieldId = pageView.getSubfield_id().get();
			visibility = ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_SUBFIELD.ARTICLES.VISIBILITY + pageView.getSubfield_id().get());
			status = ValidationHolder.getLevel(GLOBAL.VALIDATION_KEY.OWN_ENTITY_SUBFIELD.ARTICLES.STATUS + pageView.getSubfield_id().get());
		}

		if(pageView.getOriginal().equals(GLOBAL.PARAM.QUERY.IS_ORIGINAL))
			type = Lists.newArrayList(GLOBAL.RESOURCE.TYPE.ORIGINAL);
		else
			type = Lists.newArrayList(GLOBAL.RESOURCE.TYPE.ALL);


		switch (pageView.getSort()){
			case 0:
				articleList.addAll(articleMapper.selectHotByBlogIdOrSubfieldId(
						blogId,
						subfieldId,
						type,
						visibility,
						status));
				break;
			case 1:
				articleList.addAll(articleMapper.selectLatestByBlogIdOrSubfieldId(
						blogId,
						subfieldId,
						type,
						visibility,
						status));
				break;
			case 2:
				articleList.addAll(articleMapper.selectAccessByBlogIdOrSubfieldId(
						blogId,
						subfieldId,
						type,
						visibility,
						status));
				break;
			default:
				throw new RuntimeException("排序参数异常!:" + pageView.getSort());
		}

		return getArticleOverviews(PageInfo.of(articleList), articleList,
				contentMapper.batchSelectByPrimaryKeys(articleList.stream().map(BlogArticle::getId).collect(Collectors.toList())));
	}

	@Override
	public Map<String, Object> getDetail(Integer articleId) {
		ArticleView view = new ArticleView();
		BlogArticle article =
				(BlogArticle) ValidationHolder.getParam(GLOBAL.VALIDATION_KEY.CLASS_BLOG_ARTICLE.ID + articleId);

		view.setAuthor(bloggerMapper.selectByPrimaryKey(article.getBlogId()).getBlogName());
		view.setAccess(articleAccessMapper.countByArticleId(articleId));
		view.setReplyCount(articleCommentMapper.countByArticleId(articleId));

		BeanUtils.copyProperties(article, view);
		BeanUtils.copyProperties(contentMapper.selectByPrimaryKey(articleId), view);
		/* 临时修改未反应接口理念 */
		return ObjUtil.transBeanMap(view);
	//	return view;
	}

	@Override
	public Map<String, Object> getDetail(Integer uid, Integer articleId) {
		ArticleView view = new ArticleView();
		BlogArticle article =
				(BlogArticle) ValidationHolder.getParam(GLOBAL.VALIDATION_KEY.CLASS_BLOG_ARTICLE.ID + articleId);

		view.setAuthor(bloggerMapper.selectByPrimaryKey(article.getBlogId()).getBlogName());
		view.setAccess(articleAccessMapper.countByArticleId(articleId));
		view.setReplyCount(articleCommentMapper.countByArticleId(articleId));

		BeanUtils.copyProperties(article, view);
		BeanUtils.copyProperties(contentMapper.selectByPrimaryKey(articleId), view);

		if(ValidationHolder.getCurrentUser().getId().equals(article.getBlogId()))
			view.setSubfieldList(
					associativeMapper.batchSelectByArticleId(articleId)
							.stream()
							.map(BlogArticleSubfieldAssociative::getSubfieldId)
							.collect(toList()));
		/* 临时修改未反应接口理念 */
		return ObjUtil.transBeanMap(view);
//		return view;
	}

	@NotNull
	private PageInfo<ArticleView> getArticleOverviews(@NotNull PageInfo pageInfo,
													  @NotNull List<BlogArticle> articleList,
													  List<BlogArticleContent> contentList) {

		pageInfo.setList(articleList.stream().map(info ->{
			ArticleView temp = new ArticleView();
			temp.setAccess(articleAccessMapper.countByArticleId(info.getId()));
			temp.setReplyCount(articleCommentMapper.countByArticleId(info.getId()));
			BeanUtils.copyProperties(info, temp);

			Iterator<BlogArticleContent> iterator = contentList.iterator();
			while(iterator.hasNext()){
				BlogArticleContent content = iterator.next();
				if(info.getId().equals(content.getId())){
					temp.setContent(TextUtil.getInstance().getTextOverview(content.getContent(), 200));
					iterator.remove();
					break;
				}
			}
			return temp;
		}).collect(Collectors.toList()));

		return pageInfo;
	}
}
